
const inquirer = require("inquirer");
const path = require("path")
const ejs = require("ejs")
const fs = require("fs")
const axios = require('axios')
const ora = require('ora')
const Metalsmith = require('metalsmith')
// 集合了很多渲染引擎
const { render } = require('consolidate').ejs
// 用于文件拷贝
const ncp = require('ncp')
// git仓库下载操作
const { promisify } = require('util')
let downloadFn = require('download-git-repo');

downloadFn = promisify(downloadFn)//让download支持async await写法

// 方法封装
const addLoading = function (fn) {
    return async function (...args) {
        let spinner = ora("正在下载......")
        spinner.start()
        try {
            let ret = await fn(...args)
            spinner.succeed('下载成功')
            return ret
        } catch (err) {
            spinner.succeed('拉取失败')
        }
    }
}
// 获取仓库列表
const fetchRepoList = async function () {
    let { data } = await axios.get('https://api.github.com/users/zcegg/repos')
    let repos = data.map(item => item.name)
    return repos
}
// 工具方法：获取tags列表
const fetchTagList = async function (tag) {
    let { data } = await axios.get(`https://api.github.com/repos/zcegg/${tag}/tags`)
    let repos = data.map(item => item.name)
    return repos
}
// 工具方法：自定义函数完成git仓库下载操作
let dest = null
const downloadRepo = function (repo = undefined, tag = undefined) {
    //download-git-repo+缓存
    // 1、定义缓存目录
    let cacheDir = `${process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME']}/tmp/templates`
    //2、处理download-git-repo,导出的函数的调用规则 downloadFn(zcegg/create-nm#tagv)
    // let api = `zcegg/${repo}`
    // 此处换成自己的线上脚手架代码
    let api = `https://gitee.com:jmz/jmz-cli#master`
    if (tag) {
        api += `#${tag}`
    }
    console.log(api)
    console.log(cacheDir)
    // 3、自定义一个模板下载后的输出目录
    // let dest = path.resolve(cacheDir,repo)
    dest = path.resolve(cacheDir)
    let flag = fs.existsSync(dest)
    // 4、执行下载操作
    let spinner = ora("开始下载......")
    spinner.start()
    if (flag) {
        spinner.stop()
        return dest
    } else {
        downloadFn(api, dest, { clone: true })
        spinner.succeed("下载成功")
        // 5、将设置好的缓存目录返回
        return dest
    }

}
module.exports = async (proname) => {
    const repoNames = await addLoading(fetchRepoList)()

    // 设计问题
    const quesList = [
        {
            type: 'list',
            choices: repoNames,
            message: "请选择模板名称",
            name: 'repoName'
        }
    ]
    inquirer.prompt(quesList).then(async answer => {
        const tags = await addLoading(fetchTagList)(answer.repoName)
        if (tags.length) {
            let { tagv } = await inquirer.prompt({
                type: 'list',
                name: 'tags',
                message: '请选择目标版本',
                choices: tags
            })
            dest = downloadRepo(answer.repoName, tagv)

            // 二种情况
            // 1、存在ques.js，需要动态提供数据
            if (fs.existsSync(path.join(dest, 'ques.js'))) {
                await new Promise((resolve, reject) => {
                    Metalsmith(__dirname)
                        .source(dest)
                        .destination(path.resolve(proname))
                        .use(async (files, metal, done) => {
                            // files就是需要渲染的模板目录下的所有类型的文件
                            let quesArr = require(path.join(dest, 'ques.js'))
                            let answers = await inquirer.prompt(quesArr)
                            // 当前answer是传递过来的参数，我们需要在下一个use中进行使用
                            // 利用metal.metadata()来保存所有的数据，交给下一个use进行命名用即可
                            let meta = metal.metadata()
                            Object.assign(meta, answers)

                            // 删除que.js
                            delete files['ques.js']
                            done()
                        })
                        .use((files, metal, done) => {
                            let data = metal.metadata()
                            cons
                            // 找到那些需要渲染数据的具体文件，找到之后将他们里的内容转为字符串方式
                            // 转为字符串之后，接下来就是针对于字符串进行替换实现渲染
                            Reflect.ownKeys(files).forEach(async (file)=>{
                                if(file.includes('js')||file.includes('json')){
                                    let content = files[file].contents.toString()
                                    if(content.includes('<%')){
                                        content = await render(content,data)
                                        files[file].contents = Buffer.from(content)
                                    }
                                }
                            })
                            done()
                        })
                        .build((err) => {
                            if (err) {
                                reject()
                            } else {
                                resolve()
                            }
                        })
                })
            } else {
                console.log("不需要进行动态渲染")
                // 2、不存在ques.js，直接复制
                console.log()
                ncp(dest, proname)
            }

        } else {
            let { isDownload } = await inquirer.prompt({
                type: 'confirm',
                name: 'isDownload',
                message: "当前不存在多个tag是否直接下载"
            })
            if (isDownload) {
                downloadRepo()
            }
        }
    })

}